package MyFramePro.Service.Impl;

import MyFramePro.Domain.Entity.LoginUser;
import MyFramePro.Domain.Entity.User;
import MyFramePro.Domain.ResponseResult;
import MyFramePro.Domain.Vo.BlogLoginVo;
import MyFramePro.Domain.Vo.UserInfoVo;
import MyFramePro.Mapper.BlogLoginMapper;
import MyFramePro.Service.BlogLoginService;
import MyFramePro.Utils.BeanCopyUtils;
import MyFramePro.Utils.JwtUtil;
import MyFramePro.Utils.RedisCache;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;


@Service
public class BlogLoginServiceImpl extends ServiceImpl<BlogLoginMapper,User> implements BlogLoginService {

    @Resource
    private AuthenticationManager authenticationManager;    //定义了认证Authentication的方法

    @Autowired
    private RedisCache redisCache;  //这里是 redis 存入的配置类

    /**
     * 这里是登录的功能
     */
    @Override
    public ResponseResult login(User user) {

        //1.进行认证的相关操作
        UsernamePasswordAuthenticationToken authenticationToken
                = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
        Authentication authentication = authenticationManager.authenticate(authenticationToken);
        //1.1 判断认证是否通过，若认证不通过，则给出提示信息
        if(Objects.isNull(authentication)){
            throw new RuntimeException("认证失败，当前用户不存在!");
        }
        //1.2 认证通过，获取 userId，生成 token
        LoginUser loginUser =(LoginUser) authentication.getPrincipal(); //获取到认证成功的用户信息
        String userId = loginUser.getUser().getId().toString();
        String token = JwtUtil.createJWT(userId); //使用 JWT 工具类进行生成

        //2.将用户信息存入 redis 中
        redisCache.setCacheObject("front-login:"+userId,loginUser);

        //3.由于前端所需要的字段，现有类不能直接满足，所以需要 VO 类来进行实现
        //3.1 将 User 转换为 UserInfoVo
        UserInfoVo userInfoVo = BeanCopyUtils.myCopyBean(loginUser.getUser(), UserInfoVo.class);
        //3.2 将 jwt 与 UserInfoVo 封装到 BlogLoginVo 中，以满足前端字段格式
        BlogLoginVo blogLoginVo = new BlogLoginVo(token,userInfoVo);

        return ResponseResult.okResult(blogLoginVo);
    }


    /**
     * 这里是退出登录的功能
     */
    @Override
    public ResponseResult logout() {
        //1.先获取用户的 ID
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser =(LoginUser) authentication.getPrincipal();
        Long userId= loginUser.getUser().getId();

        //2.删除 redis 中的用户信息
        redisCache.deleteObject("front-login:"+userId);

        return ResponseResult.okResult();
    }

}
